#include "implementacioninterprete.h"
#include <sstream>
#include <vector>
//
implementacionInterprete::implementacionInterprete(  ){
	//por ahora no hay nada con punteros ni que inicializar
}
//
implementacionInterprete::~implementacionInterprete()
{
}
//

bool implementacionInterprete::verificarArchivosNuevos() const{
	string path = directorioPDF;
	DIR *directorio = opendir(path.c_str());
	if(directorio != NULL){
		struct dirent *pent = NULL;
        bool hayArchivos = false; 
        while ((pent=readdir(directorio))){
           if(strcmp(pent->d_name,"..")!=0 && strcmp(pent->d_name,".")!=0 && strcmp(pent->d_name,".svn")!=0){
          	hayArchivos = true;
          	break;
          }
        }
        return hayArchivos;
    }
    else{
    	return false;
   	}
}

string implementacionInterprete::nombreSinExtension(char* nombre){
	string name(nombre);
	string::size_type pos;
	
	pos = name.find(".",0);
	if(pos!=string::npos){
		name = name.substr(0,pos);
	}
	return name;
}


void implementacionInterprete::convertirDocumentoPDF(QString docName){
    /*string archivos=("");
	string pathPDF = directorioPDF;*/
	string pathTXT = directorioTxt;
	/*string pathPDFPRocesados = directorioPDFProcesados;
	DIR *directorio = opendir(pathPDF.c_str());
		
	if(directorio != NULL){
		struct dirent *pent = NULL;
        while ((pent=readdir(directorio))){
           if(strcmp(pent->d_name,"..")!=0 && strcmp(pent->d_name,".")!=0 && strcmp(pent->d_name,".svn")!=0){
           	string nombre = this->nombreSinExtension(pent->d_name);*/
           
           	//mando a generar el txt
           	string aux = docName.toStdString();
           	string txtDocName = "'" + pathTXT + "/" + aux.substr(aux.find_last_of('/') + 1, aux.size() - aux.find_last_of('/') - 5) + ".txt'"; 
           	string orden=pathPdfToText + " '" + aux + "' " + txtDocName + ">> /dev/null";
           	system(orden.c_str());
           
           	//copio el txt a la carpeta de txts para ser procesado
          	//orden = "mv " + pathPDF + "/'"  +  nombre + ".txt" + "' " + pathTXT + "/'"  + nombre + ".txt'" ;
           	//system(orden.c_str());
           	
           	//finalmente muevo el pdf a la carpeta de pdf procesados 
            //DEPRECATED!!!!
            //orden = "mv " + pathPDF + "/'"  +  pent->d_name + "' " + pathPDFPRocesados + "/'"  + pent->d_name +"'" ;
            //system(orden.c_str());
           	
           	//inserto el documento en el hash para que sea procesado
           	this->hash.insertarDocumento(aux);
           	
           //}
        //}
    //}
}


void implementacionInterprete::interpretarNuevosDocumentos(QProgressBar * progress, int cantidadDocumentos) const{
	//si hay archivos nuevos
	//if(this->verificarArchivosNuevos()){
		//string archivoProcesando;
        
        //correr el pdftotext
        //this->convertirDocumentosPDF();
        int i = 0;
        //obtengo el nombre del archivo
        string archivoProcesando = this->hash.obtenerProximoArchivoAProcesar();
        //le quito extension y ruta
        string nombre =  archivoProcesando.substr(archivoProcesando.find_last_of('/') + 1, archivoProcesando.size() - archivoProcesando.find_last_of('/') - 5);
        double acum = 0;
        while( strcmp(nombre.c_str(),"")!=0 ){
			//le quito caracteres raros y lo dejo en el directorio de TXTProcesados
			this->p.procesarDocumentoOriginal(nombre);
			if(progress != NULL)
			{
				acum += ((double)45/(double)cantidadDocumentos);
				progress->setValue(acum);
			}
			//quitar stopwords
			string archStop = nombre + "_stpwd.txt";
			this->stopword.verificarStopWord(nombre,archStop);
			if(progress != NULL)
			{
				acum += ((double)45/(double)cantidadDocumentos);
				progress->setValue(acum);
			}
			//aplicar steming
			string archStem = nombre + "_stem.txt";
			this->steming.verificarSteming(archStop,archStem);
			if(progress != NULL)
			{
				acum += ((double)5/(double)cantidadDocumentos);
				progress->setValue(acum);
			}
			//finalmente al archivo completamente procesado le asigno un id
			string id = this->hash.obtenerIdHash(archivoProcesando);
			
			//como es un documento "nuevo" debo ingresarlo como un id a procesar
			this->hash.agregarAIndexar(id);
			
			//finalmente renombro el archivo de steming con el id que me dieron
		    string orden = "mv " + directorioTxtProcesados + "/'"  +  archStem + "' " + directorioTxtProcesados + "/'"  + id +".txt'" ;
           	system(orden.c_str());
			if(progress != NULL)
			{
				acum += ((double)5/(double)cantidadDocumentos);
				progress->setValue(acum);
//				int tmp = ((i + 1) *100)/cantidadDocumentos;
//				progress->setValue(tmp);
//				i++;
			}
			archivoProcesando = this->hash.obtenerProximoArchivoAProcesar();
			nombre =  archivoProcesando.substr(archivoProcesando.find_last_of('/') + 1, archivoProcesando.size() - archivoProcesando.find_last_of('/') - 5);
		}
}


string implementacionInterprete::obtenerSoloNombre(string nombreConPath){
	string::size_type pos;
	
	pos = nombreConPath.rfind("/");
	if(pos!=string::npos){
		string nombreSolo = nombreConPath.substr(pos+1,nombreConPath.length());
		return nombreSolo;
	}
	
	
	return "";
}

//Devuelve el documento PDF original con el path pasado.
FILE* implementacionInterprete::obtenerDocumentoPDF(int idDocumento) const{
	string id;
	stringstream out;
	out << idDocumento;
	id = out.str();
	string nombre = this->hash.obtenerNombreDocumento(id);
		
	if(nombre.compare("")!=0){
		string path = nombre + ".pdf";
		return fopen(path.c_str(),"r+");
	}
}

//devuelve el documento original en TXT
FILE* implementacionInterprete::obtenerDocumentoOriginalTxt(int idDocumento) const{
	string id;
	stringstream out;
	out << idDocumento;
	id = out.str();
	string nombre = this->hash.obtenerNombreDocumento(id);
	//me quedo solo con el nombre del archivo
	nombre = this->obtenerSoloNombre(nombre);
	
	if(nombre.compare("")!=0){
		string path = directorioTxt + "/" + nombre + ".txt";
		return fopen(path.c_str(),"r+");
	}
}

//Devuelve el string del PDF PROCESADO segun el id pasado por parametro con la ruta completa
string implementacionInterprete::strObtenerDocumentoPDF(int idDocumento) const{
	string id, nombre;
	stringstream out;
	out << idDocumento;
	id = out.str();
	nombre = this->hash.obtenerNombreDocumento(id);
	return nombre;
}

//devuelve el documento a ser indexado el TXT PROCESADO
FILE* implementacionInterprete::obtenerDocumentoHash(int idDocumento) const{
	string id;
	stringstream out;
	out << idDocumento;
	id = out.str();
	string nombre = this->hash.obtenerNombreDocumento(id);
	
	if(nombre.compare("")!=0){
		string path = directorioTxtProcesados + "/" + id + ".txt";
		return fopen(path.c_str(),"r+");
	}
}

//Devuelve el string del TXT PROCESADO segun el id pasado por parametro
string implementacionInterprete::strObtenerDocumentoHash(int idDocumento) const{
	string id, nombre;
	stringstream out;
	out << idDocumento;
	id = out.str();
	nombre = this->hash.obtenerNombreDocumento(id);
	
	//me quedo solo con el nombre del archivo
	nombre = this->obtenerSoloNombre(nombre);
		
	if(nombre.compare("")!=0)
	{
		string path = directorioTxtProcesados + "/" + id + ".txt";
		return path;
	}
	return "";
}

//devuelvo el id o el valor -1 que implica que no hay mas ids a ser procesados
int implementacionInterprete::obtenerProximoIDAProcesar() const{
	string id = this->hash.obtenerProximoId();
	if(id.compare("")!=0)
		return atoi(id.c_str());
	else
		return -1;
}

vector<string> explode(string s, string e) {
 vector<string> ret;
 int iPos = s.find(e, 0);
 int iPit = e.length();
 while(iPos>-1) {
   if(iPos!=0)
     ret.push_back(s.substr(0,iPos));
   s.erase(0,iPos+iPit);  
   iPos = s.find(e, 0);    
 }
 if(s!="")
   ret.push_back(s);
 return ret;
}

string implementacionInterprete::aplicarFiltro(string frase) const{
	std::vector<std::string> words;
    words = explode(frase," ");
	vector<std::string>::iterator it;
	string fraseSalida;
	for ( it=words.begin() ; it < words.end(); it++ ){
	string palabra = *it;
		
	//transformo la frase a todo minusculas
	std::transform(palabra.begin(), palabra.end(), palabra.begin(),(int(*)(int)) std::tolower);
	
	palabra = this->p.quitarCaracteresEspeciales(palabra);
	palabra = this->p.procesarUTF8(palabra);
	//palabra = this->stopword.verificarStopWord(palabra);
	palabra = this->steming.verificarSteming(palabra);
	
	fraseSalida += palabra + " ";
	
	}
	
	return fraseSalida;

}

bool implementacionInterprete::esStopWord(string palabra) const{
	return this->stopword.esStopWord(palabra);
}

bool implementacionInterprete::esStemming(string palabra) const{
	return this->steming.esSteming(palabra);
	
}
	
string implementacionInterprete::filtrarPalabra(string palabra) const{
    std::transform(palabra.begin(), palabra.end(), palabra.begin(),(int(*)(int)) std::tolower);
    palabra = this->p.quitarCaracteresEspeciales(palabra);
	palabra = this->p.procesarUTF8(palabra);	
	return palabra;
}
	
string implementacionInterprete::aplicarStemming(string palabra) const{
	return this->steming.verificarSteming(palabra);
}

int implementacionInterprete::obtenerUltimoIdHash() const {
	return atoi(this->hash.obtenerUltimoId().c_str());
}


	